package org.budo.support.itext.pdf.renderer.factory;

import java.io.File;

import org.budo.support.itext.pdf.renderer.BudoITextPdfRenderer;
import org.budo.support.lang.util.IoUtil;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.core.io.Resource;
import org.springframework.util.ResourceUtils;
import org.xhtmlrenderer.pdf.ITextFontResolver;

import com.itextpdf.text.pdf.BaseFont;

/**
 * @author lmw
 */
public class BudoITextPdfRendererFactory implements FactoryBean<BudoITextPdfRenderer> {
    public static final String FONTS_TMP_DIR = System.getProperty("java.io.tmpdir") + File.separator + "budo-itext-pdf-fonts-tmpdir";

    private Resource[] fonts;

    public Resource[] getFonts() {
        return this.fonts;
    }

    public void setFonts(Resource[] fonts) {
        this.fonts = fonts;
    }

    @Override
    public BudoITextPdfRenderer getObject() throws Exception {
        BudoITextPdfRenderer budoITextPdfRenderer = new BudoITextPdfRenderer();
        ITextFontResolver fontResolver = budoITextPdfRenderer.getFontResolver();

        for (Resource font : this.getFonts()) {
            File file = null;

            // 字体文件路径
            if (ResourceUtils.URL_PROTOCOL_FILE.equals(font.getURL().getProtocol())) {
                file = font.getFile(); // 文件
            } else {
                file = new File(FONTS_TMP_DIR, font.getFilename()); // 临时文件
                IoUtil.write(font.getInputStream(), file); // 写临时文件
            }

            // 将字体文件路径添加到 FontResolver
            String path = file.getAbsolutePath().replaceAll("\\\\", "/");
            fontResolver.addFont(path, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        }

        // 供后续运行至确保字体文件存在
        budoITextPdfRenderer.setFonts(this.getFonts());
        return budoITextPdfRenderer;
    }

    @Override
    public Class<?> getObjectType() {
        return BudoITextPdfRenderer.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}
